package org.song.filter.certification;

import cn.hutool.core.lang.Assert;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.song.exception.MyAuthenticationException;
import org.song.util.JacksonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

/**
 * 自定义用户名密码过滤器 拦截 /login 请求 其余请求不会被拦截
 */
@Slf4j
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired(required = true)
    @Qualifier(value = "myUserDetailsServiceImpl")
    private MyUserDetailsServiceImpl myUserDetailsService;

    /**
     * 验证用户名和密码
     *
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
                || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
            final ObjectMapper mapper = new ObjectMapper();
            //取authenticationBean
            final Map<String, String> authenticationBean;
            //用try with resource，方便自动释放资源
            try (InputStream requestInputStream = request.getInputStream()) {
                // 解析请求参数
                authenticationBean = mapper.readValue(requestInputStream, Map.class);
            } catch (IOException e) {
                //将异常放到自定义的异常类中
                throw new MyAuthenticationException(e.getMessage());
            }
            Assert.isTrue(!CollectionUtils.isEmpty(authenticationBean), () -> {
                log.error("请求参数为空！" + JacksonUtil.getJsonString(request));
                return new MyAuthenticationException("请求参数为空！");
            });
            //获得账号、密码
            final String username = authenticationBean.get(SPRING_SECURITY_FORM_USERNAME_KEY);
            final String password = authenticationBean.get(SPRING_SECURITY_FORM_PASSWORD_KEY);
            //检测账号、密码是否存在
            if (myUserDetailsService.checkUsernameAndPassword(username, password)) {
                //将账号、加密后密码装入UsernamePasswordAuthenticationToken中
                final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            }
            throw new MyAuthenticationException( "账号密码错误" );
        }
        return null;
    }


}
